#ifndef SYNTACTIC_ANALYSER_H_
#define SYNTACTIC_ANALYSER_H_

#include "Driver.h"
#include "ExpressionTree.h"

#define errorLet(A, B) printError(A, B, driver); yyerrok
#define errorSkip(A, B) printError(A, B, driver); yyclearin; yyerrok
#define markLine driver.saveLine()

using namespace LALG;

#define WRITELN 1
#define READLN  2

/*-----------------------------------------------------------------------------
 *  Imprime um erro
 *-----------------------------------------------------------------------------*/
void printError(ErrorWhat what, int synToken, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Adiciona um programa
 *-----------------------------------------------------------------------------*/
void addProgram(const string* name, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Adiciona uma constante
 *-----------------------------------------------------------------------------*/
void addConstant(const string* name, const VarValue &value, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Adiciona uma variável
 *-----------------------------------------------------------------------------*/
void addVariable(const VarList* list, const VarValue &value, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Adiciona um procedimento
 *-----------------------------------------------------------------------------*/
void startProcedure(const string* name, const VarList* list, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Encerra um procedimento
 *-----------------------------------------------------------------------------*/
void endProcedure(Driver &driver);

/*-----------------------------------------------------------------------------
 *  Começa um if
 *-----------------------------------------------------------------------------*/
void startIf(const ExpressionTree* exp, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Começa um while
 *-----------------------------------------------------------------------------*/
void startWhile(const ExpressionTree* exp, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Começa um else
 *-----------------------------------------------------------------------------*/
void startElse(Driver &driver);

/*-----------------------------------------------------------------------------
 *  Termina um if
 *-----------------------------------------------------------------------------*/
void endIf(Driver &driver);

/*-----------------------------------------------------------------------------
 *  Termina um while
 *-----------------------------------------------------------------------------*/
void endWhile(Driver &driver);

/*-----------------------------------------------------------------------------
 *  Começa um repeat
 *-----------------------------------------------------------------------------*/
void startRepeat(Driver &driver);

/*-----------------------------------------------------------------------------
 *  Termina um repeat
 *-----------------------------------------------------------------------------*/
void endRepeat(const ExpressionTree* exp, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Verifica uma atribuição
 *-----------------------------------------------------------------------------*/
void checkAttribution(const string* name, const ExpressionTree* exp, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Verifica uma chamada a um procedimento
 *-----------------------------------------------------------------------------*/
void checkProcedureCall(const string* name, const VarList* list, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Verifica uma chamada a readln ou writeln
 *-----------------------------------------------------------------------------*/
void checkLineCall(int which, const VarList* list, Driver &driver);

/*-----------------------------------------------------------------------------
 *  Verifica uma expressão e retorna seu tipo
 *-----------------------------------------------------------------------------*/
int checkExpression(const ExpressionTree* exp, Driver &driver);

#endif
